//
// Created by feng on 19-3-28.
// PS: Define the sun ray data structure.
//

/*
    光线级别的并行

    ！！！！还需要更改，先用着，把整个流程走一遍，输出一个结果，以后再更改
*/

#ifndef SOLARENERGY_CHIER_SUNRAY_CUH
#define SOLARENERGY_CHIER_SUNRAY_CUH

#include <cuda_runtime.h>

namespace solar::cuda
{
    class CudaSunray
    {
        public:
            //__device__ __host__ CudaSunray() : d_samplelights_(nullptr),
            // d_perturbation_(nullptr),d_uniform_(nullptr){}
            __device__ __host__ CudaSunray() : d_samplelights_(nullptr), d_perturbation_(nullptr) {}

            __device__ __host__ CudaSunray(float3 sun_dir, int num_sunshape_groups,
                                           int num_sunshape_lights_per_group, float dni, float csr)
                : CudaSunray()
            {
                sun_dir_ = sun_dir;
                dni_ = dni;
                csr_ = csr;
                num_sunshape_groups_ = num_sunshape_groups;
                num_sunshape_lights_per_group_ = num_sunshape_lights_per_group;
            }

            __device__ __host__ ~CudaSunray();

            void CClear();

            /**
             * Getters and setters of attributes for sun ray object.
             */
            __device__ __host__ auto getSunDirection() const -> float3;
            void setSunDirection(float3 sun_dir_);

            __device__ __host__ auto getDNI() const -> float;
            void setDNI(float dni_);

            __device__ __host__ auto getCSR() const -> float;
            void setCSR(float csr_);

            __device__ __host__ auto getNumOfSunshapeGroups() const -> int;
            void setNumOfSunshapeGroups(int num_sunshape_groups_);

            __device__ __host__ auto getNumOfSunshapeLightsPerGroup() const -> int;
            void setNumOfSunshapeLightsPerGroup(int num_sunshape_lights_per_group_);

            __device__ __host__ auto getDeviceSampleLights() const -> float3*;
            void setDeviceSampleLights(float3* d_theta_);
            __device__ __host__ auto getDeviceTheta() const -> float*;
            void setDeviceTheta(float* d_theta_);
            __device__ __host__ auto getDevicePerturbation() const -> float3*;
            void setDevicePerturbation(float3* d_perturbation_);
            //__device__ __host__ float *getDeviceUniform() const;
            // void setDeviceUniform(float *d_uniform_);

            [[nodiscard]] auto getReflectiveRate() const -> float;
            void setReflectiveRate(float reflective_rate_);

            void test();

            // private:
            float3 sun_dir_ = {0, 0, 0};        // e.g.  0.306454 -0.790155   0.530793
            float dni_;                         // e.g.  1000.0
            float csr_ = 0.1;                   // e.g.  0.1
            int num_sunshape_groups_;           // e.g.  8
            int num_sunshape_lights_per_group_; // e.g.  1024
            float reflective_rate_;             // e.g.  0.88
                                    // Since all heliostats in the same scene with the same
                                    // reflective rate in our system,
                                    //  we put "reflective rate" in sunray datastructure.
                                    // One SolarScene only contains one sunray instance.
            float3* d_samplelights_; // point to sample lights memory on GPU
                                     // memory size = num_sunshape_groups_ *
                                     // num_sunshape_lights_per_group_ e.g.        = 8 * 1024
            float* d_theta_;         // 太阳入射光线径向偏移角
            // float *d_uniform_;
            float3*
                d_perturbation_; // point to perturbation memory on GPU
                                 // memory size = num_sunshape_groups_ *
                                 // num_sunshape_lights_per_group_ which obeys Gaussian distribution
    };
} // namespace solar::cuda

#endif // SOLARENERGY_CHIER_SUNRAY_CUH
